using System;
using System.Collections.Generic;
using System.Text;
using MacomberMap.Common.Components;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Xml;
using MacomberMap.Common.Logging;
using MacomberMap.Common.Types;
using System.Reflection;
using MacomberMap.Common.Events;
using MacomberMap.Common.Database_Interface;
using System.Diagnostics;

namespace MacomberMap.Common.Internals
{
    /// <summary>
    /// This class is responsible for loading, saving, and storing boundaries, substations, and lines.
    /// </summary>
    public static class MM_Repository
    {
        #region Variable declarations
        /// <summary>Our collection of substations</summary>
        public static SortedDictionary<String, MM_Substation> Substations = new SortedDictionary<string, MM_Substation>(StringComparer.CurrentCultureIgnoreCase);

        /// <summary>Our collection of companies</summary>
        public static SortedDictionary<String, MM_Company> Companies = new SortedDictionary<string, MM_Company>(StringComparer.CurrentCultureIgnoreCase);

        /// <summary>Our collection of lines</summary>
        public static SortedDictionary<String, MM_Line> Lines = new SortedDictionary<string, MM_Line>(StringComparer.CurrentCultureIgnoreCase);

        /// <summary>Our collection of DC Ties</summary>
        public static SortedDictionary<String, MM_DCTie> DCTies = new SortedDictionary<String, MM_DCTie>(StringComparer.CurrentCultureIgnoreCase);

        /// <summary>Our collection of counties</summary>
        public static MM_Indexed_Dictionary<String, MM_Boundary> Counties = new MM_Indexed_Dictionary<string, MM_Boundary>(StringComparer.CurrentCultureIgnoreCase);

        /// <summary>Our state boundary</summary>
        public static MM_Boundary StateBoundary;
        
        /// <summary>Our collection of CIM Elements and their TEIDs</summary>
        public static Dictionary<UInt64, MM_Element> TEIDs = new Dictionary<UInt64, MM_Element>();
        
        /// <summary>Our collections of elements in CIM/MM rdb we don't have positional information for.</summary>
        public static Dictionary<UInt64, MM_Element> MismatchedTEIDs = new Dictionary<ulong, MM_Element>();                            
        
        /// <summary>The collection of Events on the system</summary>
        public static Dictionary<UInt64, MM_Event> Events = new Dictionary<UInt64, MM_Event>();

        /// <summary>The collection of weather and load zones</summary>
        public static MM_Indexed_Dictionary<string, MM_Zone> Zones = new MM_Indexed_Dictionary<string, MM_Zone>(StringComparer.CurrentCultureIgnoreCase);         
       
        /// <summary>The collection of operator notes, linked to TEIDs.</summary>
        public static Dictionary<UInt64, MM_Note> Notes = new Dictionary<ulong, MM_Note>(100);

        /// <summary>The collection of available databases</summary>
        public static List<MM_Database> Databases = new List<MM_Database>(3);
        #endregion

        



        #region Conversion functions
        /// <summary>
        /// Convert text so that the first letter of each word is capitalized
        /// </summary>
        /// <param name="InString"></param>
        /// <returns></returns>
        public static string TitleCase(string InString)
        {
            if (InString == null)
                return null;
            char[] inArray = InString.ToCharArray();
            bool FirstLetter = true;
            for (int a = 0; a < inArray.Length; a++)
                if (char.IsSeparator(inArray[a]) || char.IsPunctuation(inArray[a]))
                    FirstLetter = true;
                else if (FirstLetter)
                {
                    inArray[a] = Char.ToUpper(inArray[a]);
                    FirstLetter = false;
                }
                else
                    inArray[a] = Char.ToLower(inArray[a]);
            return new string(inArray);
        }

        /// <summary>
        /// Retrieve a single-precision number, first checking for NaN
        /// </summary>
        /// <param name="Incoming">The incoming value</param>
        /// <returns></returns>
        public static Single ToSingle(Object Incoming)
        {
            if (Incoming is DBNull)
                return float.NaN;
            else if (Incoming is Single)
                return (Single)Incoming;
            else if (Incoming is Double)
                return Convert.ToSingle(Incoming);
            else if (Incoming is Decimal)
                return Convert.ToSingle(Incoming);
            else if ((String)Incoming == "NaN")
                return float.NaN;
            else if (String.IsNullOrEmpty((String)Incoming))
                return float.NaN;
            else
                return Convert.ToSingle((String)Incoming);
        }

        /// <summary>
        /// Convert an object to a UInt64 (needed for TEIDs) if possible
        /// </summary>
        /// <param name="InValue">Our incoming value</param>
        /// <param name="OutVal">Our outgoing value</param>
        /// <returns>Whether the import was succesful</returns>
        public static bool ToUInt64(object InValue, out ulong OutVal)
        {
            if (InValue is UInt64)
            {
                OutVal = Convert.ToUInt64(InValue);
                return true;
            }
            else if (InValue is Decimal)
            {
                OutVal = Convert.ToUInt64(InValue);
                return true;
            }
            else if (InValue is String)
                return UInt64.TryParse((String)InValue, out OutVal);
            else
            {
                OutVal = 0;
                return false;
            }
        }
        #endregion

        #region Lookup functions
        /// <summary>
        /// Return the base version (of our MM Common library)
        /// </summary>
        public static Version BaseVersion
        {
            get
            {
                return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;                    
            }
        }                              
        #endregion        
    }
}
